package solid;

import hdgeom.primitives.Box;

import java.awt.geom.Line2D;

import processing.core.PGraphics;
import processing.core.PVector;

public class CopyOfFace {
	PVector[] vertices;
	Box b3d;
	PVector normal;
	float d0;

	public CopyOfFace(PVector v1, PVector v2, PVector v3) {
		vertices = new PVector[] { v1, v2, v3 };
		resetBounds();
	}

	public CopyOfFace(PVector v1, PVector v2, PVector v3, PVector v4) {
		vertices = new PVector[] { v1, v2, v3, v4 };
		resetBounds();
	}

	public CopyOfFace(PVector[] vertices) {
		this.vertices = vertices;
		resetBounds();
	}

	public void calculateNormal() {
		PVector v = PVector.sub(vertices[1], vertices[0]);
		PVector u = PVector.sub(vertices[2], vertices[0]);
		normal = new PVector();
		PVector.cross(v, u, normal);
		normal.mult(1f / normal.mag());
		if (normal.z < 0) {
			invert();
			normal.mult(-1);
		}
		d0 = -this.normal.dot(vertices[0]);
	}

	public void invert() {
		PVector temp = vertices[0];
		vertices[0] = vertices[2];
		vertices[2] = temp;
	}

	public void resetBounds() {
		b3d = new Box();
		for (int i = 0; i < vertices.length; i++) {
			PVector v = vertices[i];
			b3d.addPoint(v.x, v.y, v.z);
		}
		calculateNormal();
	}

	public void display(PGraphics g) {
		if (vertices.length == 4)
			g.beginShape(PGraphics.QUADS);
		else if (vertices.length == 3)
			g.beginShape(PGraphics.TRIANGLES);
		for (int i = 0; i < vertices.length; i++) {
			PVector v = vertices[i];
			g.vertex(v.x, v.y, v.z);
		}
		g.endShape();
	}

	public boolean inside2D(float x, float y) {
		/*
		 * for (int i=0;i<3;i++){ PVector v1=vertices[i]; PVector
		 * v2=vertices[(i+1)%3]; double d=Line2D.ptSegDist(v1.x, v1.y, v2.x,
		 * v2.y, x, x); if (d<0.0001){ x+=0.01f; y+=0.01f; } }
		 */
		for (int i = 0; i < 3; i++) {
			PVector v1 = vertices[i];
			PVector v2 = vertices[(i + 1) % 3];

			double d = Line2D.ptSegDistSq(v1.x, v1.y, v2.x, v2.y, x, y);
			if (d < 0.001) {

				x += 0.001f;
				y += 0.005f;
			}
			// int res=ONLINE;
			int res = isLeft(v1, v2, x, y);
			/*
			 * while (res==ONLINE){
			 * 
			 * x+=0.001; y+=0.001; }
			 */
			if (res == RIGHT)
				return false;
		}
		return true;
	}

	final static int LEFT = 0;
	final static int RIGHT = 1;
	final static int ONLINE = 2;

	public boolean intersect(float x, float y, float z) {
		// if (z>b3d.z2)return false;
		if (!b3d.contains(x, y))
			return false;
		if (!underPlane(x, y, z))
			return false;
		if (!inside2D(x, y))
			return false;

		return true;
	}

	public int isLeft(PVector a, PVector b, float x, float y) {
		return Line2D.relativeCCW(a.x, a.y, b.x, b.y, x, y);
		/*
		 * float d=(b.x - a.x)*(y - a.y) - (b.y - a.y)*(x - a.x); if ( d> 0.001)
		 * return LEFT; if ( d< 0.001) return RIGHT; return ONLINE;
		 */
	}

	boolean underPlane(float x, float y, float z) {
		return normal.dot(x, y, z) + d0 < 0;
	}
}
